home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-21 / printit2.zip / PRINTIT.ASM < prev    next >
Assembly Source File  |  1992-05-11  |  16KB  |  493 lines

  1. title   PRINTIT.COM   A program that just copies a file to LPT1
  2.  
  3. comment *
  4.         This program just copies a file or files to LPT1.  It DOES NOT
  5.         check to see if LPT1 is ready, and will loop endlessly if LPT1
  6.         is not ready.  Mostly for use under Desqview since "copy filename
  7.         lpt1" is an internal command, and DV will not do much in the middle
  8.         of an internal command.
  9.  
  10.         PRINTIT inserts a form feed between files and after the last file
  11.         printed.
  12.  
  13. Usage:
  14.         PRINTIT filespec
  15.  
  16. "filespec" may include a path and/or wildcard characters.
  17.  
  18. To create PRINTIT.COM:
  19.         MASM PRINTIT;
  20.         LINK PRINTIT;
  21.         EXE2BIN PRINTIT.EXE PRINTIT.COM
  22.  
  23. This program is released into the public domain.
  24.  
  25. Jon Fleming (BIX jfleming)
  26.  
  27. Version 1.0: 9/28/88
  28.  
  29. Revised 5/11/92 version 2.0:  see the READ.ME file
  30.  
  31. *
  32.  
  33.  
  34. buffer_size     equ     10240           ;Nice fat 10K buffer for file reads.
  35.                                         ; Must be at least 256.
  36.  
  37. stack_size      equ     256
  38.  
  39. cr              equ     0dh
  40. lf              equ     0ah
  41. tab             equ     9
  42. TRUE            equ     1
  43. FALSE           equ     0
  44.  
  45. stack   segment stack           ;just to keep the linker quiet
  46. stack   ends
  47.  
  48. code    segment
  49.  
  50. data    segment byte
  51.  
  52. bad_memory_message      db      cr,lf,"Not enough memory",cr,lf,"$"
  53. no_filespec_message     db      cr,lf,"No file specified",cr,lf,"$"
  54. no_file_found_message   db      cr,lf,"No matching file found",cr,lf,"$"
  55. cant_open_message       db      cr,lf,"Can't open file",cr,lf,"$"
  56. user_prompt_message     db      cr,lf,"Filespec to print (<Enter> to quit): $"
  57. curr_dir_message        db      cr,lf,"Default directory is: $"
  58. end_error_message       db      "Press any key to continue ...$"
  59.  
  60. at_end_of_file          db      FALSE
  61. desqview_present        db      FALSE
  62.  
  63. filename_start  dw      ?       ;pointer to first character after path
  64.  
  65. chars_in_buffer dw      ?
  66.  
  67. file_handle     dw      ?
  68.  
  69. curr_drive      db      " :\$"
  70.  
  71. ;file name as typed on the command line
  72. cmd_line_file_name      label   byte
  73.                 db      7Fh     ; 127 characters max user input
  74.  
  75. ;here we get a little tricky; the following uninitialized data is done
  76. ;  this way so we don't need room for it in the disk file PRINTIT.COM
  77.  
  78. ;path + file name returned by DOS find-file
  79. full_file_name          equ     cmd_line_file_name
  80.  
  81. ;Disk Transfer Area
  82. DTA             equ     cmd_line_file_name + 128
  83. found_file_name equ     DTA + 30
  84.  
  85. ;buffer for reading from the file
  86. buffer          equ     DTA + 128
  87. end_buffer      equ     buffer + buffer_size + 1
  88.  
  89. data    ends
  90.  
  91.         program group   code, data
  92.  
  93.         org     80h             ;command tail in the PSP
  94. cmd_tail_length         db      ?
  95. cmd_tail                db      ?
  96.  
  97.         org     100h
  98.         assume  cs:program,ds:program,es:program,ss:program
  99.  
  100. begin:
  101.         cld
  102.  
  103.         mov     bx, offset program:end_buffer
  104.         add     bx,stack_size           ;locate end of program
  105.  
  106.         cmp     sp,bx
  107.         jae     ok_to_move_stack
  108.  
  109.         mov     dx,offset program:bad_memory_message
  110.         jmp     error_exit
  111.  
  112. ok_to_move_stack:
  113.         cli
  114.         mov     sp,bx                   ;relocate stack
  115.         sti
  116.  
  117.         add     bx,15
  118.         mov     cl,4
  119.         shr     bx,cl                   ;program size in paragraphs
  120.  
  121.         mov     ah,4ah
  122.         int     21h                     ;release unused memory
  123.  
  124.         jnc     memory_ok               ;If we didn't have that much memory,
  125.                                         ; DOS reports an error
  126.  
  127.         mov     dx,offset program:bad_memory_message
  128.         jmp     error_exit
  129.  
  130. memory_ok:
  131.         mov     cx,"DE"
  132.         mov     dx,"SQ"
  133.         mov     ax,2b01h
  134.         int     21h                     ; Check if Desqview is present
  135.  
  136.         cmp     al,0ffh
  137.         je      check_command_tail
  138.  
  139.         mov     desqview_present,TRUE   ; Desqview's here, save for later
  140.  
  141. check_command_tail:
  142.         call    scan_cmd_tail           ;get filespec to print
  143.         jnc     something_present       ;there's SOMETHING on the command line
  144.  
  145.         mov     ah,09h                  ; Nothing on the command line,
  146.         mov     dx,offset program:curr_dir_message
  147.         int     21h
  148.  
  149.         mov     ah,19h
  150.         int     21h                     ; Get the current drive number
  151.         add     al,41h                  ; Convert it to an uppercase letter
  152.         mov     curr_drive,al           ; And store it away
  153.  
  154.         mov     ah,09h
  155.         mov     dx, offset program:curr_drive
  156.         int     21h                     ; Print the current drive
  157.  
  158.         mov     ah,47h
  159.         xor     dl,dl
  160.         mov     si,offset program:buffer
  161.         int     21h                     ; Get the current default directory
  162.  
  163.         mov     di,offset program:buffer
  164.         xor     al,al
  165.         mov     cx,0ffh
  166.         cld
  167.         repne   scasb                   ; Locate the zero-terminator
  168.  
  169.         dec     di
  170.         mov     al,"$"
  171.         stosb                           ; Replace it with a "$"
  172.  
  173.         mov     ah,09h
  174.         mov     dx,offset program:buffer
  175.         int     21h                     ; Display default directory
  176.  
  177.         mov     ah,09h
  178.         mov     dx,offset program:user_prompt_message
  179.         int     21h                     ; Ask the user for a filespec
  180.  
  181.         mov     ah,0Ah
  182.         mov     dx,offset program:cmd_line_file_name
  183.         int     21h                     ; Get the user's input
  184.  
  185.         mov     cl,cmd_line_file_name+1
  186.         xor     ch,ch
  187.         push    cx                      ; Save count of amount of input
  188.         or      cl,cl
  189.         jnz     bump_user_input_over
  190.         jmp     normal_exit             ; If no input, quit
  191.  
  192. bump_user_input_over:
  193.         mov     di,offset program:cmd_line_file_name
  194.         mov     si,di
  195.         inc     si
  196.         inc     si
  197.  
  198.         cld
  199.  
  200.         rep     movsb                   ; Shift the user's input over two to
  201.                                         ;   cover the max input count and
  202.                                         ;   actual input count
  203.         pop     cx                      ; Remember the count of input
  204.         mov     si,offset program:cmd_line_file_name    ; Restore pointer
  205.                                         ;    to start of filespec
  206.         jmp     short filespec_present
  207.  
  208. something_present:
  209.         or      al,al                   ;is it a switch?
  210.         jz      filespec_present
  211.  
  212.         mov     dx,offset program:no_filespec_message
  213.         jmp     short error_exit
  214.  
  215. filespec_present:                       ; Now let's move the file to another
  216.                                         ;  buffer so we can handle wild cards
  217.         mov     ax,offset program:full_file_name
  218.         mov     filename_start,ax       ;initialize pointer to start of
  219.                                         ;file name
  220.  
  221.         mov     di,offset program:cmd_line_file_name
  222.  
  223. move_filename:
  224.         lodsb
  225.         stosb
  226.  
  227.         cmp     al,":"                  ;check for end-of-path characters
  228.         je      update_pointer_to_start
  229.         cmp     al,"\"
  230.         jne     end_move_filename_loop
  231.  
  232. update_pointer_to_start:
  233.         mov     filename_start,di
  234.  
  235. end_move_filename_loop:
  236.         loop    move_filename
  237.  
  238.         xor     al,al
  239.         stosb                           ;make it null-terminated
  240.  
  241.         mov     dx,offset program:DTA
  242.         mov     ah,1ah
  243.         int     21h                     ;set up our Disk Transfer Area
  244.  
  245.         mov     cx,00100011b            ;normal, archive, hidden, or read-only attributes
  246.         mov     ah,4eh
  247.         mov     dx,offset program:full_file_name
  248.         int     21h                     ;search for first matching file
  249.  
  250.         jnc     ready_to_print          ;found one
  251.  
  252.         mov     dx,offset program:no_file_found_message
  253.  
  254. error_exit:
  255.         mov     ah,9
  256.         int     21h                     ;print error message
  257.  
  258.         cmp     desqview_present, TRUE  ; Is desqview around?
  259.         jne     actual_error_exit       ; Nope
  260.  
  261.         mov     ah,9                    ; Yup, print a message ...
  262.         mov     dx,offset program:end_error_message
  263.         int     21h
  264.  
  265.         mov     ah,07h                  ; And wait for the user to hit a key
  266.         int     21h                     ;  so the window doesn't close
  267.  
  268. actual_error_exit:
  269.         mov     ax,4c01h
  270.         int     21h                     ;terminate, return code 1
  271.  
  272. ready_to_print:
  273.         mov     si,offset program:found_file_name
  274.         mov     di,filename_start
  275.  
  276. construct_full_name:
  277.         lodsb
  278.         stosb                           ;append file name to path (if there is
  279.                                         ;       one)
  280.         or      al,al                   ;hit the end?
  281.         jz      open_file               ;yep
  282.  
  283.         jmp     construct_full_name     ;nope
  284.  
  285. open_file:
  286.         mov     ax,3d00h
  287.         mov     dx,offset program:full_file_name
  288.         int     21h                     ;open the file
  289.  
  290.         jnc     opened_file             ;if a path was included, a match will
  291.                                         ;be found, but this simple-minded
  292.                                         ;OPEN won't work
  293.  
  294.         mov     dx,offset program:cant_open_message
  295.         jmp     error_exit
  296.  
  297. opened_file:
  298.         mov     file_handle,ax          ;save handle
  299.         mov     at_end_of_file,FALSE    ;initialize EOF flag
  300.  
  301. read_into_buffer:
  302.         mov     bx,file_handle
  303.         mov     cx,buffer_size
  304.         mov     dx,offset program:buffer
  305.         mov     ah,3fh
  306.         int     21h                     ;read into buffer
  307.  
  308.         mov     chars_in_buffer, ax     ;save actual number of chars read
  309.  
  310.         cmp     ax,buffer_size          ;got a full buffer?
  311.         je      prepare_to_print        ;yep
  312.  
  313.         mov     at_end_of_file, TRUE    ;nope, must be at end of file
  314.         
  315. prepare_to_print:
  316.         mov     si,offset program:buffer
  317.         mov     cx,chars_in_buffer
  318.  
  319.         jcxz    look_for_next_file      ;skip if buffer empty (file size is
  320.                                         ;  a multiple of buffer size)
  321. print_loop:
  322.         lodsb
  323.         mov     dl,al                   ;next character
  324.         mov     ah,5
  325.         int     21h                     ;print it
  326.  
  327.         loop    print_loop
  328.  
  329.         cmp     at_end_of_file,TRUE     ;more characters?
  330.         jne     read_into_buffer
  331.  
  332. look_for_next_file:
  333.         mov     bx,file_handle
  334.         mov     ah,3eh
  335.         int     21h                     ;close the current file
  336.  
  337.         mov     dl,12
  338.         mov     ah,5
  339.         int     21h                     ;form feed between files or @ end
  340.  
  341.         mov     ah,4fh
  342.         int     21h                     ;search for next matching file
  343.  
  344.         jc      normal_exit             ;none found, all done
  345.  
  346.         jmp     ready_to_print          ;found another file, go print it
  347.  
  348. normal_exit:
  349.         mov     ax,4c00h
  350.         int     21h                     ;terminate, return code 0
  351.  
  352. current_cmd_tail_position       dw      0       ;storage for use by
  353. characters_left_in_cmd_tail     db      0ffh    ;scan_cmd_tail
  354.  
  355.  
  356. scan_cmd_tail   proc    near
  357. ;procedure to get parameters off the command line.  If no more parameters
  358. ;are present, returns carry set.  If the next parameter is a switch (prefixed
  359. ;by "/" or "-"), the switch is returned in AL (converted to uppercase) and
  360. ;SI will point to the first character after the switch.
  361. ;Otherwise, AL will be zero; SI will point to the beginning of the
  362. ;parameter; and CX will contain the length of the parameter.  In any case,
  363. ;SI, AH and CX are destroyed
  364.  
  365.         push    dx
  366.  
  367.         clc                             ;assume more characters in tail
  368.  
  369.         cmp     characters_left_in_cmd_tail,0ffh        ;assuming the command
  370.         jne     not_first_call          ;tail isn't ever really this long
  371.  
  372.         mov     al,cmd_tail_length
  373.         inc     al                              ;include <return> in count
  374.         mov     characters_left_in_cmd_tail,al
  375.         mov     ax,offset program:cmd_tail      ;initialize our variables
  376.         mov     current_cmd_tail_position,ax
  377.  
  378.         mov     cl,cmd_tail_length
  379.         xor     ch,ch
  380.         jcxz    no_more_parameters
  381.  
  382.         mov     si,ax                           ;set up to capitalize the
  383.         mov     di,ax                           ;entire command tail
  384.  
  385. capitalize_cmd_tail_loop:
  386.         lodsb
  387.         cmp     al,'a'
  388.         jb      end_capitalize_loop
  389.         cmp     al,'z'
  390.         ja      end_capitalize_loop
  391.  
  392.         and     al,0dfh                 ;convert to uppercase
  393.  
  394. end_capitalize_loop:
  395.         stosb
  396.         loop    capitalize_cmd_tail_loop
  397.  
  398. not_first_call:
  399.         mov     cl,characters_left_in_cmd_tail
  400.         xor     ch,ch
  401.         jcxz    no_more_parameters
  402.  
  403.         mov     si,current_cmd_tail_position
  404.  
  405. scan_tail_loop:
  406.         lodsb                           ;get next character
  407.         dec     cx
  408.  
  409.         cmp     al,' '                  ;see if it's whitespace
  410.         je      scan_tail_loop
  411.         cmp     al,tab
  412.         je      scan_tail_loop
  413.  
  414.         cmp     al,cr                   ;check for end of tail
  415.         je      no_more_parameters
  416.  
  417.         cmp     al,'/'                  ;found something, is it a switch?
  418.         je      found_a_switch
  419.         cmp     al,'-'
  420.         je      found_a_switch
  421.  
  422.         call    scan_a_non_switch       ;it's not a switch, scan it
  423.         inc     cx                      ;correct character count
  424.  
  425.         xor     al,al                   ;flag that a non-switch was found
  426.  
  427.         jmp     short finished_scan_cmd_tail
  428.  
  429. found_a_switch:
  430.         lodsb                           ;get the switch
  431.         dec     cx
  432.  
  433.         push    ax                      ;save it
  434.  
  435.         call    scan_a_non_switch       ;get any trailing string
  436.  
  437.         pop     ax                      ;restore switch
  438.         inc     si                      ;make SI point to trailing chars
  439.  
  440.         jmp     short finished_scan_cmd_tail
  441.  
  442. no_more_parameters:
  443.         stc
  444.  
  445. finished_scan_cmd_tail:
  446.         pop     dx
  447.         ret
  448.  
  449. scan_a_non_switch       proc    near
  450. ;scans through a non-switch string or the string following a switch to
  451. ;find the end and the length.
  452.         push    si                      ;found a non-switch, save beginning
  453.         push    cx
  454.  
  455. loop_over_nonswitch_chars:
  456.         lodsb                           ;get next character
  457.         dec     cx
  458.  
  459.         cmp     al,' '                  ;see if it's whitespace
  460.         je      found_end_of_nonswitch
  461.         cmp     al,tab
  462.         je      found_end_of_nonswitch
  463.         cmp     al,'-'                  ;or maybe it's the beginning of
  464.         je      found_end_of_nonswitch  ;another switch
  465.         cmp     al,'/'
  466.         je      found_end_of_nonswitch
  467.  
  468.         cmp     al,cr                   ;check for end of tail
  469.         jne     loop_over_nonswitch_chars
  470.  
  471. found_end_of_nonswitch:
  472.         dec     si
  473.         mov     current_cmd_tail_position,si    ;save our state for next call
  474.         inc     cl
  475.         mov     characters_left_in_cmd_tail,cl
  476.  
  477.         mov     dx,cx                   ;get character count
  478.         pop     cx
  479.         sub     cx,dx
  480.  
  481.         pop     si                      ;get pointer to beginning of string     
  482.         dec     si
  483.  
  484.         ret
  485. scan_a_non_switch       endp
  486.  
  487. scan_cmd_tail   endp
  488.  
  489. code    ends
  490. end     begin
  491. 
  492.  
  493.